/*
 * @(#)BasicAuthenticator.java
 *
 * Copyright (c) 2003 DCIVision Ltd
 * All rights reserved.
 *
 * This software is the confidential and proprietary information of DCIVision
 * Ltd ("Confidential Information").  You shall not disclose such Confidential
 * Information and shall use it only in accordance with the terms of the license
 * agreement you entered into with DCIVision Ltd.
 */
package com.dcivision.user.auth;

import java.io.IOException;
import java.sql.Connection;
import java.sql.SQLException;

import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.dcivision.framework.ApplicationException;
import com.dcivision.framework.BASE64Utility;
import com.dcivision.framework.Crypt;
import com.dcivision.framework.DataSourceFactory;
import com.dcivision.framework.ErrorConstant;
import com.dcivision.framework.GlobalConstant;
import com.dcivision.framework.SessionContainer;
import com.dcivision.framework.SystemParameterConstant;
import com.dcivision.framework.SystemParameterFactory;
import com.dcivision.framework.Utility;
import com.dcivision.ldap.core.LdapAuthenticationHandler;
import com.dcivision.user.bean.UserRecord;
import com.dcivision.user.dao.UserRecordDAObject;

/**
BasicAuthenticator.java

This class is responsible for Basic authenticator.

  @author          Charlie Liu
  @company         DCIVision Limited
  @creation date   06/06/2005
  @version         $Revision: 1.2.4.3 $
*/
public class BasicAuthenticationHandler {


    private String defaultDomain;
    private String domainController;
    private String realm="";
    private Log logger = null;
    private UserRecord authUser = null;

    /**
     * Constructor
     *
     */
  public BasicAuthenticationHandler(){
        logger = LogFactory.getLog(this.getClass().getName());
  }

  /**
   * authenticator - BAISC authentication.
   *
   * @param request
   * @param response
   */
  public boolean authenticate(ServletRequest request,
            ServletResponse response)throws IOException, ServletException{
        HttpServletRequest req;
        HttpServletResponse resp;
        String msg;
        req = (HttpServletRequest)request;
        resp = (HttpServletResponse)response;
        msg = req.getHeader( "Authorization" );
        logger.debug("msg : "+msg);

        if( msg != null && msg.startsWith( "Basic" )) {
                //String  auth = new sun.misc.BASE64Decoder().decodeBuffer(msg.substring(6));
                String auth = new String(BASE64Utility.decode(msg.substring(6)),"US-ASCII");
                int index = auth.indexOf(':');
                String user = (index != -1) ? auth.substring(0, index) : auth;
                String password = (index != -1) ? auth.substring(index + 1) : "";
                index = user.indexOf('\\');
                if (index == -1) index = user.indexOf('/');
                user = (index != -1) ? user.substring(index + 1) : user;
                //logger.debug("XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX");                
                //logger.debug("user:"+user);
                //logger.debug("password:"+password);
                //logger.debug("XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX");                
            if(authenticateUser(req,user,password)){              
              //logger.debug("Basic.Name ::"+authUser.getLoginName()+"Basic.Password ::" +authUser.getLoginPwd());
              return true;
            }else{
              resp.setHeader( "WWW-Authenticate", "Basic realm=\"" + realm + "\"");
              resp.setStatus( HttpServletResponse.SC_UNAUTHORIZED );
              resp.flushBuffer();
              return false;
            }
        }else {
            HttpSession ssn = req.getSession(false);
            if (ssn == null || ( authUser= (UserRecord)req.getAttribute("AuthUserRecord")) == null) {
                resp.setHeader( "WWW-Authenticate", "Basic realm=\"" + realm + "\"");
                resp.setStatus( HttpServletResponse.SC_UNAUTHORIZED );
                resp.flushBuffer();
                return false;
            }else{
              return true;
            }
        }
  }

  protected boolean authenticateUser(HttpServletRequest req, String userName, String password) throws ApplicationException{
      SessionContainer sessionCtn = new SessionContainer();
      String loginMethod = SystemParameterFactory.getSystemParameter(SystemParameterConstant.LOGIN_METHOD);
      Connection conn = null;
      boolean loginSucessFlag=false;
      try {
        conn = DataSourceFactory.getConnection();
        UserRecordDAObject userRecordDAO = new UserRecordDAObject(sessionCtn, conn);
        UserRecord userRecord = (UserRecord) userRecordDAO.getObjectByLoginName(userName, GlobalConstant.RECORD_STATUS_ACTIVE);

        // Check User Record ID = 0 for administrator account access,
        // LDAP login doesn't support administrator account.
        if(userRecord!=null){
          if(userRecord.getID().intValue() == 0
          || Utility.isEmpty(loginMethod)
          || loginMethod.equals(GlobalConstant.LOGIN_METHOD_PARADM))
          {
            String encrptedPwd = Crypt.encrypt(password, SystemParameterFactory.getSystemParameter(SystemParameterConstant.CRYPTO_SALT));
            loginSucessFlag=encrptedPwd.equals(userRecord.getLoginPwd());
          }else if(loginMethod.equals(GlobalConstant.LOGIN_METHOD_LDAP) || loginMethod.equals(GlobalConstant.LOGIN_METHOD_NTLM)){
            LdapAuthenticationHandler ldapAuthentication=new LdapAuthenticationHandler();
            loginSucessFlag=ldapAuthentication.login(userName,password);
          }
        }
        if(loginSucessFlag){
          AuthenticationHandler authHandler = null;
          try 
          {            
            conn = com.dcivision.framework.DataSourceFactory.getConnection();
            try{
              authHandler = (AuthenticationHandler)Class.forName(SystemParameterFactory.getSystemParameter(SystemParameterConstant.AUTHENICATION_CLASS)).newInstance();
            }catch(Exception err){
              throw new ApplicationException(ErrorConstant.LOGIN_AUTH_CLASS_NOT_FOUND);            
            }
            authHandler.initializeLoginUser(userName, req, conn);
            conn.commit();            
          } catch (Exception err) {
            try{ conn.rollback(); }catch(java.sql.SQLException sqlerr){}
          }       
          req.setAttribute("AuthUserRecord",userRecord);
        }
        return loginSucessFlag;
      }catch (Exception e) {
        throw new ApplicationException(ErrorConstant.COMMON_FATAL_ERROR);
      }finally{
        try {
          if(conn!=null) conn.close();
        }catch (SQLException e) {
          throw new ApplicationException(ErrorConstant.DB_GENERAL_ERROR);
        }finally{
          conn=null;
        }
     }
  }
}